package com.zjb.demo.common.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.noear.redisx.RedisClient;
import org.noear.redisx.Serializer;
import org.noear.redisx.plus.RedisBucket;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;
import org.noear.solon.cache.jedis.RedisCacheService;
import org.noear.solon.data.cache.CacheService;
import org.noear.solon.data.cache.impl.JsonSerializer;

/**
 * @author 庄佳彬
 * @since 2023/12/23 22:07
 */
@Configuration
public class RedisConfig {

    @Bean
    public RedisClient redisClient(@Inject("${redis}") RedisClient client) {
        client.serializer(new Serializer() {

            private final static ObjectMapper mapper;

            static {
                mapper = JsonMapper.builder()
                        .configure(MapperFeature.USE_GETTERS_AS_SETTERS, false)
                        .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
                        .build();
                mapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY);
                mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
            }

            @Override
            public String encode(Object value) {
                if (value == null) {
                    return "{}";
                }
                try {
                    return mapper.writeValueAsString(value);
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                }
            }

            @Override
            public Object decode(String str, Class<?> clz) {
                try {
                    return mapper.readValue(str, clz);
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        return client;
    }

    @Bean
    public RedisBucket redisBucket(@Inject RedisClient client) {
        return client.getBucket();
    }

    @Bean
    public CacheService cacheService(@Inject RedisClient client) {
        return new RedisCacheService(client, 30) {
            @Override
            public String newKey(String key) {
                return key;
            }
        }.serializer(JsonSerializer.instance);
    }

}
